// gui/GuiSlider.cpp

#include "GuiSlider.h"
#include <gfx/Texture.h>

TypeId GUI::GuiSlider::s_TypeId = "GuiSlider";

using namespace GUI;

void GuiSlider::SetupGuiSlider( float32_t fMinValue,
								float32_t fMaxValue,
								GFX::Texture * pBarTexture,
								GFX::Texture * pNotchTexture)
{
	m_fMinValue = fMinValue;
	m_fMaxValue = fMaxValue;
	m_fCurrentValue = 0.0f;

	m_pBarTexture = pBarTexture;
	m_pNotchTexture = pNotchTexture;

	Math::vec3 vPos(0.0f, 0.0f, 0.0f);
	CORE::Colour colWhite(255, 255, 255);

	m_fSliderWidth = static_cast<float32_t>(pBarTexture->GetWidth());

	m_BarSprite.SetupGuiComponent(GetName() + "_BARSPRITE");
	m_BarSprite.SetupGuiSprite(vPos, pBarTexture, colWhite);
	GetFrame().AttachFrame(&m_BarSprite.GetFrame());

	m_NotchSprite.SetupGuiComponent(GetName() + "_BARNOTCH");
	m_NotchSprite.SetupGuiSprite(vPos, pNotchTexture, colWhite);
	GetFrame().AttachFrame(&m_NotchSprite.GetFrame());

	float32_t fHalfWidth = static_cast<float32_t>(pBarTexture->GetWidth()) / 2.0f;
	float32_t fHalfHeight = static_cast<float32_t>(pNotchTexture->GetHeight()) / 2.0f;

	m_HotSpotRect.SetRect( -fHalfWidth, fHalfHeight, fHalfWidth, -fHalfHeight);
	m_HotSpotRect.SetFrame( &GetFrame() );
	SetHotSpot( &m_HotSpotRect );

	SetVisible( true );
}

bool GuiSlider::OnSelect(float32_t fX, float32_t fY)
{
	bool bSuccess = GuiSelectable::OnSelect(fX, fY);

	if (bSuccess)
	{
		Math::vec3 vCurrentPos = m_NotchSprite.GetLocalPosition();

		const Math::mat4 matInvWorld = m_HotSpotRect.GetFrame()->GetWorldMatirx().Inverse();
		Math::vec3 vLocalPos = matInvWorld.MultiplyTransform3(Math::vec3(fX, fY, 0.0f));
		float32_t fXPos = vLocalPos.x;

		float32_t fLambda = (fXPos + m_fSliderWidth /2.0f) / m_fSliderWidth;
		m_fCurrentValue = Math::Tabi_Interpolate(fLambda, m_fMinValue, m_fMaxValue);

	}

	return bSuccess;
}

void GuiSlider::Render( IRenderingEngine * pRenderer )
{
	if (IsVisible())
	{
		float32_t fRange = (m_fMaxValue - m_fMinValue) * m_fSliderWidth;
		float32_t fLambda = (m_fCurrentValue - m_fMinValue) / (m_fMaxValue - m_fMinValue);
		Math::vec3 vBarPos = m_NotchSprite.GetFrame().GetLocalPosition();
		float32_t fHalfGraphicWidth = static_cast<float32_t>(m_pBarTexture->GetWidth()) / 2.0f;

		vBarPos.x = Math::Tabi_Interpolate(fLambda, -fHalfGraphicWidth, fHalfGraphicWidth);

		m_NotchSprite.SetPosition(vBarPos);

		if (m_bVisualDirty)
		{
			GFX::VisualSprite * pBarSprite = static_cast<GFX::VisualSprite *>(m_BarSprite.GetVisual());
			GFX::VisualSprite * pNotchSprite = static_cast<GFX::VisualSprite *>(m_NotchSprite.GetVisual());

			CORE::Colour colColour(255, 255, 255);

			if (IsHighlightable())
			{
				if (IsActive())
					colColour.SetColour(255, 255, 255);
				else
					colColour.SetColour(128, 128, 128);
			}
			else
				colColour.SetColour(64, 64, 64);

			pBarSprite->SetColour(colColour);
			pNotchSprite->SetColour(colColour);

			m_bVisualDirty = false;
		}

		m_BarSprite.Render(pRenderer);
		m_NotchSprite.Render(pRenderer);

		GuiSelectable::Render(pRenderer);
	}
}